package stock.avanza;

import static java.util.Calendar.*;

import java.net.URL;
import java.util.Calendar;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import misc.BenchTimer;
import misc.Helpers;
import misc.StringTemplate;
import stock.Sale;
import stock.Stock;

import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

import ernie.database.Database;
import graph.autodrawer.AutoDrawer;

/**
 * @author Filip Lindqvist <buggfille@gmail.com>
 * @author Fredrik Persson
 * @created 11:02:33 PM - Nov 24, 2011
 */
public class ScrapeThread implements Runnable {

    private final int SLOW_DELAY_MAX = 350000;
    private final int SLOW_DELAY_MIN = 250000;
    private final int FAST_DELAY = 8000;
    private final int FAST_DURATION = 60000;
    private final StringTemplate SLOW_URL = new StringTemplate(
            "https://www.avanza.se/aza/aktieroptioner/kurslistor/avslut.jsp?orderbookId=${id}",
            "${id}");

    private ScrapeTask task;
    private final Timer timer;
    private final Stock stock;
    private final Database db;
    private final Login login;
    private long fastUntil;
    private boolean fast = true;
    private final AutoDrawer autoDrawer;

    public ScrapeThread(Stock stock, Database db, Login login,
            AutoDrawer autoDrawer) {
        this.autoDrawer = autoDrawer;
        this.login = login;
        this.stock = stock;
        this.db = db;
        timer = new Timer(stock.toString() + "-thread");
        task = new ScrapeTask(stock, db, login, autoDrawer);
        fastUntil = 0;

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    if (System.currentTimeMillis() > fastUntil) {
                        setFastUpdate(false);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }).start();
    }

    @Override
    public void run() {
    }

    public void setFastUpdate(boolean fastUpdate) {

        if (fastUpdate) {
            fastUntil = System.currentTimeMillis() + FAST_DURATION;
            if (fast == false) {
                System.out.println("Fast updates for " + stock);
                task.cancel();
                task = new ScrapeTask(stock, db, login, autoDrawer);
                task.setTemplateUrl(SLOW_URL);
                task.setFastUpdate(true);
                timer.schedule(task, 0, FAST_DELAY);
                fast = true;
            }
        } else {
            if (fast == true) {
                task.cancel();
                task = new ScrapeTask(stock, db, login, autoDrawer);
                task.setTemplateUrl(SLOW_URL);
                task.setFastUpdate(false);
                timer.schedule(
                        task,
                        0,
                        (int) ((SLOW_DELAY_MAX - SLOW_DELAY_MIN)
                                * Math.random() + SLOW_DELAY_MIN));
                fast = false;
            }
        }
    }

    private static class ScrapeTask extends TimerTask {

        private final Stock stock;
        private final Database database;
        private StringTemplate url;
        private WebClient client;
        private final Login login;
        private boolean fastUpdate;
        private final AutoDrawer autoDrawer;

        public ScrapeTask(Stock stk, Database db, Login login,
                AutoDrawer autoDrawer) {
            this.autoDrawer = autoDrawer;
            stock = stk;
            database = db;
            this.login = login;
            client = Helpers.createNewAndSilenceWebClient();
        }

        public void setTemplateUrl(StringTemplate url) {
            this.url = url;
        }

        public void setFastUpdate(boolean fastUpdate) {
            this.fastUpdate = fastUpdate;
        }

        @Override
        public void run() {
            Calendar calendarInstance = Calendar.getInstance();
            int hour = calendarInstance.get(HOUR_OF_DAY);
            int day = calendarInstance.get(DAY_OF_WEEK);

            if (day != SATURDAY && day != SUNDAY && 8 <= hour && hour <= 18) {
                login.makeLoggedIn(client);
                try {
                    String url = this.url.toString(stock.getId());
                    WebRequest request = new WebRequest(new URL(url),
                            HttpMethod.GET);
                    HtmlPage page = client.getPage(request);

                    BenchTimer b = new BenchTimer("fetch sales from page");
                    List<Sale> sales = stock.getAvanzaSales(page);
                    b.terminate();
                    database.saveEntries(sales);
                    if (fastUpdate) {
                        autoDrawer.triggerDraw(stock.toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("Creating new webclient for "
                            + stock.toString());
                    client = Helpers.createNewAndSilenceWebClient();
                    login.makeLoggedIn(client);
                    run();
                }
            }
        }
    }
}
